/**
 * 
 */
package com.shine.icis.blo.imp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import com.shine.icis.blo.IMainMonitorService;
import com.shine.icis.config.SysCodeDictLoader;
import com.shine.icis.dao.IETLLogDAO;
import com.shine.icis.dao.IMetadataCheckLogDAO;
import com.shine.icis.dto.DictOption;
import com.shine.icis.dto.MonitorConsole;
import com.shine.icis.dto.MonitorConsole.MonitorInfo;
import com.shine.icis.dto.MonitorConsole.MonitorItem;
import com.shine.icis.hbean.ETLRunLog;
import com.shine.icis.hbean.ProgExeLog;
import com.shine.icis.util.Tools;

/**
 * @author zsy
 *
 */
public class MainMonitorService implements IMainMonitorService {

	private IETLLogDAO etlLogDAO;
	private IMetadataCheckLogDAO metadataCheckDAO;
	
	public void setEtlLogDAO(IETLLogDAO etlLogDAO) {
		this.etlLogDAO = etlLogDAO;
	}
	
	public void setMetadataCheckDAO(IMetadataCheckLogDAO metadataCheckDAO) {
		this.metadataCheckDAO = metadataCheckDAO;
	}


	@Override
	public MonitorConsole getMonitorConsole() {
		MonitorConsole mc = new MonitorConsole();
		//运行服务器是否活动
//		mc.setServerActived(etlContextVarService.getTaskServerActived());
		
		Collection<DictOption> systems = SysCodeDictLoader.getInstance().getBizSystemOptions();
		if (systems == null || systems.isEmpty()) {
			return mc;
		}
		//取得最后一次过程开始日志
		ProgExeLog lastStartProLog = etlLogDAO.findLastStartProcess();
		if (lastStartProLog == null) {//无日志，从没运行过
			return mc;
		}
		mc.setStartLogID(lastStartProLog.getLogID());
		
		//过滤日志的开始时间
		int operDate = lastStartProLog.getOperDate();
		int operTime = lastStartProLog.getOperTime();
		
		List<MonitorInfo> mis = new ArrayList<MonitorInfo>(systems.size());
		mc.setMonitorInfos(mis);
		
		for (DictOption sys : systems) {
			MonitorInfo mi = mc.new MonitorInfo();
			mi.setSystemName(sys.getText());//系统名称
			mi.setSystemCode(sys.getKey());
			
			MonitorItem item = mc.new MonitorItem();
			initMonitorInfo(item, Integer.parseInt(sys.getKey()), ProgExeLog.ETL_PROC_ID_EXCRACT, operDate, operTime);
			mi.setExtractItem(item);
			
			item = mc.new MonitorItem();
			initMonitorInfo(item, Integer.parseInt(sys.getKey()), ProgExeLog.ETL_PROC_ID_LOAD, operDate, operTime);
			mi.setLoadItem(item);
			
			item = mc.new MonitorItem();
			initMonitorInfo(item, Integer.parseInt(sys.getKey()), ProgExeLog.ETL_PROC_ID_TRANSFORM, operDate, operTime);
			mi.setTransformItem(item);
			mis.add(mi);
		}

		//判断转换是否都结束
		boolean traEnded = false;
		List<ProgExeLog> progLogs = etlLogDAO.findProgExeLogs(ProgExeLog.ETL_PROC_ID_TRANSFORM, operDate, operTime);
		if (progLogs != null && !progLogs.isEmpty()) {//转换的控制日志不为空
			Set<Integer> bizSystemEnds = new HashSet<Integer>();//记录已结束的系统，除重复
			for (ProgExeLog pl : progLogs) {
				if (pl.getRunStatus() == ETLRunLog.RUN_STATUS_START) {
					continue;//忽略开始的
				}
				bizSystemEnds.add(pl.getDatasetTypeID());
			}
			if (bizSystemEnds.size() == SysCodeDictLoader.getInstance().getBizSystemOptions().size()) {
				//所有系统都结束，采集过程才算结束
				traEnded = true;
			}
		}
		
		//取得最后一次过程开始日志时间之后的结束日志
//		ProgExeLog lastEndProLog = etlLogDAO.findLastEndProcess(operDate, operTime);
		if (!traEnded) {//还未结束
			mc.setServerStatus("任务于" + formatDate(operDate, operTime) + "开始。");
//			mc.setCheckInfo("");
			//从数据库读取服务器状态
		} else {//已结束，加载元数据质量检查信息
			ProgExeLog lastEndProLog = progLogs.get(progLogs.size() - 1);//取最后一条的时间
			mc.setServerStatus("任务于" + formatDate(operDate, operTime) + "开始，" + formatDate(lastEndProLog.getOperDate(), lastEndProLog.getOperTime()) + "结束，数据采集准备完毕。");
		}
		
		//元数据质量检查信息
		
		//查找质量检查的执行日志
		List<ProgExeLog> mdProgLog = etlLogDAO.findProgExeLogs(ProgExeLog.ETL_PROC_ID_METADATACHECK, operDate, operTime);
		if (mdProgLog == null || mdProgLog.isEmpty()) {//无记录，未开始
			mc.setChekStatus(-1);
		} else {
			//查找质量检查下一步骤的执行日志
			mdProgLog = etlLogDAO.findProgExeLogs(ProgExeLog.ETL_PROC_ID_TRANSFORM, operDate, operTime);
			if (mdProgLog != null && !mdProgLog.isEmpty()) {//下一步骤有日志说明上一步骤已经结束
				mc.setChekStatus(1);//
			} else {//否则处于运行中
				mc.setChekStatus(0);
			}
		}
		
		if (mc.getChekStatus() != -1) {//运行中或已结束，才去查询信息
			List<Integer> traLogs = metadataCheckDAO.findMetadataCheckLogPrepLevelIDs(operDate, operTime, ETLRunLog.PREP_LEVEL_ID_WARN);
			if (traLogs == null || traLogs.isEmpty()) {
				mc.setCheckInfo("无警告信息。");
			} else {
				//统计
				Map<Integer, Integer> stat = new TreeMap<Integer, Integer>();
				for (Integer l : traLogs) {
					Integer count = stat.get(l);
					if (count == null) {
						count = 1;
					} else {
						count++;
					}
					stat.put(l, count);
				}
				StringBuffer msg = new StringBuffer();
				for (Integer key : stat.keySet()) {
					String prepLevelText = SysCodeDictLoader.getInstance().getPrepLevelOptionText(key.toString());
					msg.append(prepLevelText).append("[").append(stat.get(key)).append("] ");
				}
				mc.setCheckInfo(msg.toString());
			}
		
//			mc.setCheckInfo("运行状态：元数据检查结束<br />告警状况：无警告信息。<br />详细日志：查看");
		}
		return mc;
	}
	
	/**
	 * 格式化标准日期与时间格式
	 * @param operDate
	 * @param operTime
	 * @return
	 */
	static String formatDate(int operDate, int operTime) {
		StringBuffer dsb = new StringBuffer();
		dsb.append(operDate);
		if (dsb.length() != 8) {
			return "";
		}
		dsb.insert(6, "-").insert(4, "-").toString();
		
		StringBuffer tsb = new StringBuffer();
		tsb.append(Tools.getFixedNum(operTime, 6));
		tsb.insert(4, ":").insert(2, ":").toString();
		
		dsb.append(" ").append(tsb);
		return dsb.toString();
	}
	
	private void initMonitorInfo(MonitorItem item, int datasetTypeID, int etlProcID, int operDate, int operTime) {
		//找出任务的日志，每步有两条，一条开始一条结束
		List<ProgExeLog> jobLogs = etlLogDAO.findProgExeLogs(datasetTypeID, etlProcID, operDate, operTime);		
		if (jobLogs == null || jobLogs.isEmpty()) {//无日志，未开始
			item.setRunStatus(MonitorItem.STATUS_NORUN);
			item.setAlarmInfo("");
		} else {
			item.setRunStatus(MonitorItem.STATUS_RUNNING);//默认开始状态
			for (ProgExeLog log : jobLogs) {
				if (log.getRunStatus() == ETLRunLog.RUN_STATUS_SUCCESS) {//有成功LOG状态为成功
					item.setRunStatus(MonitorItem.STATUS_SUCCESS);
				} else if (log.getRunStatus() == ETLRunLog.RUN_STATUS_FAILURE) {//有失败LOG状态为失败
					item.setRunStatus(MonitorItem.STATUS_FAILURE);
				}
			}
			
			List<Integer> traLogs = etlLogDAO.findETLRunLogPrepLevelIDs(datasetTypeID, etlProcID, operDate, operTime, ETLRunLog.PREP_LEVEL_ID_WARN);
			if (traLogs == null || traLogs.isEmpty()) {
				item.setAlarmInfo("无警告信息。");
			} else {
				//统计
				Map<Integer, Integer> stat = new TreeMap<Integer, Integer>();
				for (Integer l : traLogs) {
					Integer count = stat.get(l);
					if (count == null) {
						count = 1;
					} else {
						count++;
					}
					stat.put(l, count);
				}
				StringBuffer msg = new StringBuffer();
				for (Integer key : stat.keySet()) {
					String prepLevelText = SysCodeDictLoader.getInstance().getPrepLevelOptionText(key.toString());
					msg.append(prepLevelText).append("[").append(stat.get(key)).append("] ");
				}
				item.setAlarmInfo(msg.toString());
			}
		}
	}
}
//mi = mc.new MonitorInfo();
//mi.setSystemName("法人清算");
//i1 = mc.new MonitorItem();
//i1.setRunResult(MonitorItem.RESULT_NOEND);
//i1.setRunStatus(MonitorItem.STATUS_NORUN);
//i1.setAlarmInfo("");
//mi.setExtractItem(i1);
//i2 = mc.new MonitorItem();
//i2.setRunResult(MonitorItem.RESULT_NOEND);
//i2.setRunStatus(MonitorItem.STATUS_NORUN);
//i2.setAlarmInfo("");
//mi.setLoadItem(i2);
//i3 = mc.new MonitorItem();
//i3.setRunResult(MonitorItem.RESULT_NOEND);
//i3.setRunStatus(MonitorItem.STATUS_NORUN);
//i3.setAlarmInfo("");
//mi.setTransformItem(i3);
//mis.add(mi);
//
//mi = mc.new MonitorInfo();
//mi.setSystemName("银企划付");
//i1 = mc.new MonitorItem();
//i1.setRunResult(MonitorItem.RESULT_NOEND);
//i1.setRunStatus(MonitorItem.STATUS_NORUN);
//i1.setAlarmInfo("");
//mi.setExtractItem(i1);
//i2 = mc.new MonitorItem();
//i2.setRunResult(MonitorItem.RESULT_NOEND);
//i2.setRunStatus(MonitorItem.STATUS_NORUN);
//i2.setAlarmInfo("");
//mi.setLoadItem(i2);
//i3 = mc.new MonitorItem();
//i3.setRunResult(MonitorItem.RESULT_NOEND);
//i3.setRunStatus(MonitorItem.STATUS_NORUN);
//i3.setAlarmInfo("");
//mi.setTransformItem(i3);
//mis.add(mi);